/**HEADER********************************************************************
* 
* Copyright (c) 2011 Freescale Semiconductor;
* All Rights Reserved
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: lwgpio_mcf51mm.c$
* $Version : 3.8.5.1$
* $Date    : Feb-13-2012$
*
* Comments:
*
*   This file contains the GPIO standard functions used on boards
*
*END************************************************************************/

#include "mqx.h"
#include "bsp.h"
#include "lwgpio.h"

/*** FLAGS for LWGPIO_STRUCT.flags ***/

/**************************************************************************
 * int.mask * int.src * direction * int.mode * port number  *  pin index  *
 *  8bits   *  2bits  *   1 bit   *   3bits  *    8bits     *    3bits    *
 **************************************************************************/

/* - pin index */
#define LWGPIO_PIN_SHIFT (0)
#define LWGPIO_PIN_MASK (0x7 << LWGPIO_PIN_SHIFT)
#define LWGPIO_PIN(x) (((x) << LWGPIO_PIN_SHIFT) & LWGPIO_PIN_MASK)
#define LWGPIO_PIN_FROM_ID(id) (((id) & LWGPIO_PIN_MASK) >> LWGPIO_PIN_SHIFT)

/* - port number */
#define LWGPIO_PORT_SHIFT (3)
#define LWGPIO_PORT_MASK (0xFF << LWGPIO_PORT_SHIFT)
#define LWGPIO_PORT(x) (((x) << LWGPIO_PORT_SHIFT) & LWGPIO_PORT_MASK)
#define LWGPIO_PORT_FROM_ID(id) (((id) & LWGPIO_PORT_MASK) >> LWGPIO_PORT_SHIFT)

/* - int. mode */
#define LWGPIO_INT_MODE_SHIFT (11)
#define LWGPIO_INT_MODE_MASK (0x03 << LWGPIO_INT_MODE_SHIFT)
#define LWGPIO_INT_MODE(x) (((x) << LWGPIO_INT_MODE_SHIFT) & LWGPIO_INT_MODE_MASK)
#define LWGPIO_INT_MODE_FROM_ID(id) (((id) & LWGPIO_INT_MODE_MASK) >> LWGPIO_INT_MODE_SHIFT)

/* - direction */ 
/*
#define LWGPIO_DIR_SHIFT (13)
#define LWGPIO_DIR_MASK (0x01 << LWGPIO_DIR_SHIFT)
*/

/* - int. source (KBI1, KBI2, IRQ pin) */
#define LWGPIO_INT_SRC_SHIFT (14)
#define LWGPIO_INT_SRC_MASK (0x03 << LWGPIO_INT_SRC_SHIFT)
#define LWGPIO_INT_SRC(x) (((x) << LWGPIO_INT_SRC_SHIFT) & LWGPIO_INT_SRC_MASK)
#define LWGPIO_INT_SRC_FROM_ID(id) (((id) & LWGPIO_INT_SRC_MASK) >> LWGPIO_INT_SRC_SHIFT) 

/* - int. mask */
#define LWGPIO_INT_PINMASK_SHIFT (16)
#define LWGPIO_INT_PINMASK_MASK (0xFF << LWGPIO_INT_PINMASK_SHIFT)
#define LWGPIO_INT_PINMASK(x) (((x) << LWGPIO_INT_PINMASK_SHIFT) & LWGPIO_INT_PINMASK_MASK)
#define LWGPIO_INT_PINMASK_FROM_ID(id) (((id) & LWGPIO_INT_PINMASK_MASK) >> LWGPIO_INT_PINMASK_SHIFT) 

/* interrupt sources */
#define LWGPIO_INT_SRC_KBI1    (0)
#define LWGPIO_INT_SRC_KBI2    (1)
#define LWGPIO_INT_SRC_IRQ     (2)

/* */
#define LWGPIO_PTA_KBI1_MASK   (0x0E)
#define LWGPIO_PTB_KBI1_MASK   (0xC0)
#define LWGPIO_PTC_KBI1_MASK   (0x1C)
#define LWGPIO_PTC_KBI2_MASK   (0xE0)
#define LWGPIO_PTE_KBI2_MASK   (0x0F)
#define LWGPIO_PTE_IRQ_MASK    (0x10)    
#define LWGPIO_PTF_KBI2_MASK   (0x20)

/* IRQ SC Pins which are not defined in processor header */
#define LWGPIO_IRQSC_ES        (0x20)
#define LWGPIO_IRQSC_PE        (0x10)

/*** GLOBALS ***/

static const VMCF51MM_GPIO_DATA_STRUCT_PTR lwgpio_data_ptr[GPIO_PORT_MAX] =
{
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_A),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_B),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_C),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_D),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_E),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_F),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_G),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_H),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_DATA_J)
};

static const VMCF51MM_GPIO_STRUCT_PTR lwgpio_ptr[GPIO_PORT_MAX] =
{
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_A]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_B]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_C]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_D]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_E]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_F]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_A_G[GPIO_PORT_G]),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_H),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->GPIO_J)   
};

/* pointers to interrupt status registers - sorted according to LWGPIO_INT_SRC_* */
static volatile uchar * lwgpio_int_regsc[] = {
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI1.KBISC),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI2.KBISC),
    &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->IRQ.IRQSC)
};

/* interrupt vectors - sorted according to LWGPIO_INT_SRC_* */
static const MCF51MM_INTERRUPT_TABLE_INDEX lwgpio_int_vectors[] = {
    MCF51MM_INT_Vkeyboard1,
    MCF51MM_INT_Vkeyboard2,
    MCF51MM_INT_Virq
};


/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_init
* Returned Value   : TRUE if succesfull, FALSE otherwise
* Comments         :
*    Decodes ID to HW specific struct and then performs pin initialization
*
*END*********************************************************************/
boolean lwgpio_init
(
    /* Pointer to LWGPIO internal structure to be filled in */
    LWGPIO_STRUCT_PTR handle,
    /* Pin ID, bitmask integer value */
    LWGPIO_PIN_ID     id,
    /* Direction to be set within initialization */
    LWGPIO_DIR        dir,
    /* Value to be set within initialization */
    LWGPIO_VALUE      value
)
{ /* Body */

    uint_32 port_idx, pin_idx;

    port_idx = LWGPIO_PORT_FROM_ID(id);
    pin_idx = LWGPIO_PIN_FROM_ID(id);

    handle->port_idx = port_idx;
    handle->pinmask = 1 << pin_idx;
    handle->flags = id;        

    /* Set value prior to set to output */
    if (value != LWGPIO_VALUE_NOCHANGE) {
        /* Note: there is no check for values not defined as LWGPIO_VALUE enum */
        lwgpio_set_value(handle, value);
    }

    if (dir != LWGPIO_DIR_NOCHANGE) {
        /* Note: there is no check for values not defined as LWGPIO_DIR enum */
        lwgpio_set_direction(handle, dir);
    }

    return TRUE;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_set_attribute
* Returned Value   : TRUE if succesfull, FALSE otherwise
* Comments         :
*    Sets attributes
*
*END*********************************************************************/
boolean lwgpio_set_attribute
(
    /* Pin handle to get function from */
    LWGPIO_STRUCT_PTR  handle,
    /* PORT attribute */
    uint_32 attribute_id,
    /* Attribute value */
    uint_32 value
)
{
    switch(attribute_id)
    {
        case(LWGPIO_ATTR_PULL_UP):
        {
            if(value == LWGPIO_AVAL_ENABLE)
            {
                lwgpio_ptr[handle->port_idx]->PTxPE |= handle->pinmask;
            }
            else        /* value == LWGPIO_AVAL_DISABLE */
            {
                lwgpio_ptr[handle->port_idx]->PTxPE &= ~(handle->pinmask);
            }
            break;
        }
        case(LWGPIO_ATTR_SLEW_RATE):
        {
            if(value == LWGPIO_AVAL_ENABLE)
            {
                lwgpio_ptr[handle->port_idx]->PTxSE |= handle->pinmask;
            }
            else        /* value == LWGPIO_AVAL_DISABLE */
            {
                lwgpio_ptr[handle->port_idx]->PTxSE &= ~(handle->pinmask);
            }
            break;
        }
        case(LWGPIO_ATTR_FILTER):
        {
            if(value == LWGPIO_AVAL_ENABLE)
            {
                lwgpio_ptr[handle->port_idx]->PTxIFE |= handle->pinmask;
            }
            else        /* value == LWGPIO_AVAL_DISABLE */
            {
                lwgpio_ptr[handle->port_idx]->PTxIFE &= ~(handle->pinmask);
            }
            break;
        }
        case(LWGPIO_ATTR_DRIVE_STRENGTH):
        {
            if(value == LWGPIO_AVAL_DRIVE_STRENGTH_HIGH)
            {
                lwgpio_ptr[ handle->port_idx ]->PTxDS |= handle->pinmask;
            }
            else        /* value == LWGPIO_AVAL_DRIVE_STRENGTH_LOW */
            {
                lwgpio_ptr[handle->port_idx]->PTxDS &= ~(handle->pinmask);
            }
            break;
        }
        default:
        {
            return FALSE;
        }
    }
    return TRUE;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_set_functionality
* Returned Value   : void
* Comments         :
*    Sets functionality (peripheral mode) of the pin
*
*END*********************************************************************/
void lwgpio_set_functionality
(
    /* Pin handle to set function on */
    LWGPIO_STRUCT_PTR  handle, 
    /* Function to be set (integer value) */
    uint_32            function
)
{
    return;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_get_functionality
* Returned Value   : void
* Comments         :
*    Gets function (peripheral mode) of the pin
*
*END*********************************************************************/
uint_32 lwgpio_get_functionality
(
    /* Pin handle to get function from */
    LWGPIO_STRUCT_PTR  handle
)
{
    return 0;
}


/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_set_direction
* Returned Value   : void
* Comments         :
*    Sets direction of the pin
*
*END*********************************************************************/
void lwgpio_set_direction
(
    /* Pin handle to set direction on */
    LWGPIO_STRUCT_PTR  handle, 
    /* Direction to be set */
    LWGPIO_DIR         dir
)
{
    if ( dir == LWGPIO_DIR_INPUT )
    {
        lwgpio_data_ptr[ handle->port_idx ]->PTxDD &= ~handle->pinmask;
    }
    else if ( dir == LWGPIO_DIR_OUTPUT )
    {
        lwgpio_data_ptr[ handle->port_idx ]->PTxDD |= handle->pinmask;
    }
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_set_value
* Returned Value   : void
* Comments         :
*    Sets value (output latch) of the pin
*
*END*********************************************************************/
void lwgpio_set_value
(
    /* Pin handle to set value on */
    LWGPIO_STRUCT_PTR  handle, 
    /* Direction to be set */
    LWGPIO_VALUE       out_value
)
{
    if ( out_value == LWGPIO_VALUE_LOW )
    {
        lwgpio_data_ptr[ handle->port_idx ]->PTxD &= ~handle->pinmask;
    }
    else if ( out_value == LWGPIO_VALUE_HIGH )
    {
        lwgpio_data_ptr[ handle->port_idx ]->PTxD |= handle->pinmask;
    }

}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_toggle_value
* Returned Value   : void
* Comments         :
*    Toggles value of output latch of the pin
*
*END*********************************************************************/
void lwgpio_toggle_value
(
    /* Pin handle to toggle value on */
    LWGPIO_STRUCT_PTR  handle
)
{
    lwgpio_set_value(handle, lwgpio_get_value(handle) == LWGPIO_VALUE_HIGH ? LWGPIO_VALUE_LOW : LWGPIO_VALUE_HIGH);    
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_get_value
* Returned Value   : LWGPIO_VALUE of pin status
* Comments         :
*    Returns value (output latch or read data) of the pin
*
*END*********************************************************************/
LWGPIO_VALUE lwgpio_get_value
(
    /* Pin handle to get value from */
    LWGPIO_STRUCT_PTR  handle
)
{
    return ( lwgpio_data_ptr[ handle->port_idx ]->PTxD & handle->pinmask ) ? LWGPIO_VALUE_HIGH : LWGPIO_VALUE_LOW;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_get_raw
* Returned Value   : LWGPIO_VALUE of pin status
* Comments         :
*    Returns read level of the pin
*
*END*********************************************************************/
LWGPIO_VALUE lwgpio_get_raw
(
    /* Pin handle to get value from */
    LWGPIO_STRUCT_PTR  handle
)
{
    return ( lwgpio_data_ptr[ handle->port_idx ]->PTxD & handle->pinmask ) ? LWGPIO_VALUE_HIGH : LWGPIO_VALUE_LOW;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_int_init
* Returned Value   : TRUE if succesfull, FALSE otherwise
* Comments         :
*    Initializes pin to generate interrupt
*
*END*********************************************************************/
boolean lwgpio_int_init
(
    /* Pin handle to initialize interrupt on */
    LWGPIO_STRUCT_PTR handle,
    /* Interrupt mode */
    LWGPIO_INT_MODE   mode
)
{ /* Body */

    uchar int_src  = 0;
    uchar int_mask = 0;
    
    volatile uchar * reg_es[] = {
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI1.KBIES),
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI2.KBIES),
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->IRQ.IRQSC)
    };
    
    volatile uchar * reg_pe[] = {
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI1.KBIPE),
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->KBI2.KBIPE),
        &(((VMCF51MM_STRUCT_PTR)BSP_IPSBAR)->IRQ.IRQSC)
    };
    
    uchar reg_es_edg;
    uchar reg_pe_pe;

    uchar int_enabled;    
        
    switch( handle->port_idx ) {
    
        case GPIO_PORT_A:
            
            /* PTA3 to PTA1 -> KBI1P2 to KBI1P0*/
            if ( handle->pinmask & ~LWGPIO_PTA_KBI1_MASK ) 
                return FALSE;
            int_src = LWGPIO_INT_SRC_KBI1;
            reg_es_edg = reg_pe_pe = handle->pinmask >> 1;
            break;
            
        case GPIO_PORT_B:
            
            /* PTB7, PTB6 -> KBI1P4, KBI1P3 */
            if ( handle->pinmask & ~LWGPIO_PTB_KBI1_MASK ) 
                return FALSE;
            int_src = LWGPIO_INT_SRC_KBI1;
            reg_es_edg = reg_pe_pe = handle->pinmask >> 3;            
            break;
            
        case GPIO_PORT_C:
            
            /* PTC4 to PTC2 -> KBI1P7 to KBI1P5 */
            if ( handle->pinmask & LWGPIO_PTC_KBI1_MASK ) {
                int_src = LWGPIO_INT_SRC_KBI1;
                reg_es_edg = reg_pe_pe = handle->pinmask << 3; 
            }                                              
            /* PTC7 to PTC5 -> KBI2P2 to KBI2P0 */
            else if ( handle->pinmask & LWGPIO_PTC_KBI2_MASK ) {
                int_src = LWGPIO_INT_SRC_KBI2;
                reg_es_edg = reg_pe_pe = handle->pinmask >> 5;
            } 
            else
                return FALSE;            
            break;
            
        case GPIO_PORT_E:
            
            /* PTE3 to PTE0 -> KBI2P6 to KBI2P3 */
            if ( handle->pinmask & LWGPIO_PTE_KBI2_MASK ) {
                int_src = LWGPIO_INT_SRC_KBI2;
                reg_es_edg = reg_pe_pe = handle->pinmask  << 3;
            } else if ( handle->pinmask & LWGPIO_PTE_IRQ_MASK ) {
            /* PTE4 -> IRQ */
                int_src    = LWGPIO_INT_SRC_IRQ;
                reg_es_edg = LWGPIO_IRQSC_ES;
                reg_pe_pe  = LWGPIO_IRQSC_PE;
            } else {
                return FALSE;
            }            
            break;
            
        case GPIO_PORT_F:
            
            /* PTF5 -> KBI2P7 */
            if ( handle->pinmask & ~LWGPIO_PTF_KBI2_MASK ) 
                return FALSE;
            int_src = LWGPIO_INT_SRC_KBI2;
            reg_es_edg = reg_pe_pe = handle->pinmask << 2;            
            break;
            
        default:
            return FALSE;
    }    
      
    /* for the next code:
       MCF51XX_KBIXSC_KBIE, MCF51XX_KBIXSC_KBMOD and MCF51XX_KBIXSC_KBIE are
       KBIxSC pinmasks valid also for appropriate IRQSC pins */
    
    /* mask ints */
    int_enabled = *lwgpio_int_regsc[int_src] & MCF51XX_KBIXSC_KBIE;
    *lwgpio_int_regsc[int_src] &= ~MCF51XX_KBIXSC_KBIE; 
    
    /* select pin polarity */
    if ( mode == LWGPIO_INT_MODE_FALLING || mode == LWGPIO_INT_MODE_LOW )        
        *reg_es[int_src] &= ~reg_es_edg;
    else if ( mode == LWGPIO_INT_MODE_RISING || mode == LWGPIO_INT_MODE_HIGH )    
        *reg_es[int_src] |= reg_es_edg;
    else {
        if( int_enabled )        
            *lwgpio_int_regsc[int_src] |= MCF51XX_KBIXSC_KBIE;
        return FALSE;
    }     
    /* want level detect? */              
    if( mode == LWGPIO_INT_MODE_LOW || mode == LWGPIO_INT_MODE_HIGH )
        *lwgpio_int_regsc[int_src] |= MCF51XX_KBIXSC_KBIMOD;
        
    /* pull up / pull down */    
    /* -> let the user do this */
    
    /* enable ints */
    *reg_pe[int_src] |= reg_pe_pe;
    
    /* clear false ints */
    *lwgpio_int_regsc[int_src] |= MCF51XX_KBIXSC_KBACK;
        
    handle->flags |= LWGPIO_INT_SRC( int_src );
     
    if( int_enabled )        
        *lwgpio_int_regsc[int_src] |= MCF51XX_KBIXSC_KBIE;
    
    return TRUE;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_int_enable
* Returned Value   : void
* Comments         :
*    Enables / disables interrupts for specified pin
*
*END*********************************************************************/
void lwgpio_int_enable
(
    /* Pin handle to enable interrupt on */
    LWGPIO_STRUCT_PTR handle,
    /* Enable or disable interrupt? TRUE = enable */
    boolean           ena
)
{
    /* MCF51XX_KBIXSC_KBIE is valid IE pin mask also for IRQSC */
    if( ena )        
        *lwgpio_int_regsc[ LWGPIO_INT_SRC_FROM_ID(handle->flags) ] |= MCF51XX_KBIXSC_KBIE;
    else
        *lwgpio_int_regsc[ LWGPIO_INT_SRC_FROM_ID(handle->flags) ] &= ~MCF51XX_KBIXSC_KBIE;
    return; 
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_int_get_flag
* Returned Value   : TRUE if interrupt flag is set
* Comments         :
*    Checks if there is pending interrupt flag for specified pin
*
*END*********************************************************************/
boolean lwgpio_int_get_flag
(
    /* Pin handle to get interrupt flag on */
    LWGPIO_STRUCT_PTR handle
)
{
        /* MCF51XX_KBIXSC_KBF is valid interrupt flag pin mask also for IRQSC */ 
    return *lwgpio_int_regsc[ LWGPIO_INT_SRC_FROM_ID(handle->flags) ] & MCF51XX_KBIXSC_KBF ? TRUE : FALSE;
}

/*FUNCTION*****************************************************************
* 
* Function Name    : lwgpio_int_clear_flag
* Returned Value   : void
* Comments         :
*    Clears pending interrupt flag on peripheral
*
*END*********************************************************************/
void lwgpio_int_clear_flag
(
    /* Pin handle to clear interrupt flag on */
    LWGPIO_STRUCT_PTR handle
)
{
    /* MCF51XX_KBIXSC_KBACK is valid ACK pin mask also for IRQSC */
    *lwgpio_int_regsc[ LWGPIO_INT_SRC_FROM_ID(handle->flags) ] |= MCF51XX_KBIXSC_KBACK;       
    return;   
}


/*FUNCTION****************************************************************
* 
* Function Name    : lwgpio_int_get_vector
* Returned Value   : vector index
* Comments         :
*    This function returns vector index for specified pin
*
*END*********************************************************************/
uint_32 lwgpio_int_get_vector
(
    /* Pin handle to get vector of */
    LWGPIO_STRUCT_PTR  handle
)
{
    return lwgpio_int_vectors[ LWGPIO_INT_SRC_FROM_ID(handle->flags) ];
}
